package algorithms

import (
	"fmt"
	"log"
	"math"
	"sort"
	"strings"
	"time"

	"navigation-service/internal/models"
)

// GroupingManager 分组管理器
type GroupingManager struct {
	algorithms map[string]models.GroupingAlgorithm
}

// NewGroupingManager 创建分组管理器
func NewGroupingManager() *GroupingManager {
	manager := &GroupingManager{
		algorithms: make(map[string]models.GroupingAlgorithm),
	}

	// 注册算法
	manager.RegisterAlgorithm(&FrequencyGroupingAlgorithm{})
	manager.RegisterAlgorithm(&TimePatternGroupingAlgorithm{})
	manager.RegisterAlgorithm(&ContentSimilarityGroupingAlgorithm{})
	manager.RegisterAlgorithm(&AIEnhancedGroupingAlgorithm{})

	return manager
}

// RegisterAlgorithm 注册算法
func (gm *GroupingManager) RegisterAlgorithm(algorithm models.GroupingAlgorithm) {
	gm.algorithms[algorithm.GetName()] = algorithm
}

// GetAlgorithm 获取算法
func (gm *GroupingManager) GetAlgorithm(name string) (models.GroupingAlgorithm, error) {
	algorithm, exists := gm.algorithms[name]
	if !exists {
		return nil, fmt.Errorf("算法 %s 不存在", name)
	}
	return algorithm, nil
}

// ListAlgorithms 列出所有算法
func (gm *GroupingManager) ListAlgorithms() []models.GroupingAlgorithm {
	var algorithms []models.GroupingAlgorithm
	for _, algorithm := range gm.algorithms {
		algorithms = append(algorithms, algorithm)
	}
	return algorithms
}

// GroupURLs 使用指定算法分组URL
func (gm *GroupingManager) GroupURLs(algorithmName string, features []models.URLFeature, config models.AIGroupingConfig) ([]models.AIGroup, error) {
	algorithm, err := gm.GetAlgorithm(algorithmName)
	if err != nil {
		return nil, err
	}

	return algorithm.GroupURLs(features, config)
}

// 频率分组算法实现
type FrequencyGroupingAlgorithm struct{}

func (f *FrequencyGroupingAlgorithm) GetName() string {
	return "frequency"
}

func (f *FrequencyGroupingAlgorithm) GetDescription() string {
	return "基于访问频率的分组算法"
}

func (f *FrequencyGroupingAlgorithm) GroupURLs(features []models.URLFeature, config models.AIGroupingConfig) ([]models.AIGroup, error) {
	log.Printf("=== 开始频率分组算法 ===")
	log.Printf("输入特征数量: %d", len(features))

	if len(features) == 0 {
		log.Printf("特征为空，返回空分组")
		return []models.AIGroup{}, nil
	}

	// 步骤1: 按访问频率排序
	log.Printf("步骤1: 按访问频率排序URL特征")
	sort.Slice(features, func(i, j int) bool {
		return features[i].VisitCount > features[j].VisitCount
	})

	// 打印排序后的前5个URL
	log.Printf("排序后前5个URL:")
	for i := 0; i < len(features) && i < 5; i++ {
		log.Printf("  %d. %s (访问次数: %d)", i+1, features[i].URL, features[i].VisitCount)
	}

	// 步骤2: 设置分组参数
	log.Printf("步骤2: 设置分组参数")
	minGroupSize := config.MinGroupSize
	if minGroupSize <= 0 {
		minGroupSize = 3
	}

	maxGroupSize := config.MaxGroupSize
	if maxGroupSize <= 0 {
		maxGroupSize = 20
	}

	log.Printf("最小分组大小: %d, 最大分组大小: %d", minGroupSize, maxGroupSize)

	// 步骤3: 计算频率阈值
	log.Printf("步骤3: 计算频率阈值")
	totalVisits := 0
	for _, feature := range features {
		totalVisits += feature.VisitCount
	}

	avgVisits := float64(totalVisits) / float64(len(features))
	highFreqThreshold := avgVisits * 2.0
	mediumFreqThreshold := avgVisits * 0.5
	veryHighFreqThreshold := avgVisits * 4.0
	veryLowFreqThreshold := avgVisits * 0.1

	log.Printf("总访问次数: %d", totalVisits)
	log.Printf("平均访问次数: %.2f", avgVisits)
	log.Printf("极高频阈值: %.2f", veryHighFreqThreshold)
	log.Printf("高频阈值: %.2f", highFreqThreshold)
	log.Printf("中频阈值: %.2f", mediumFreqThreshold)
	log.Printf("低频阈值: %.2f", veryLowFreqThreshold)

	var groups []models.AIGroup
	groupID := 1

	// 步骤4: 创建极高频访问组
	log.Printf("步骤4: 创建极高频访问组")
	veryHighFreqURLs := []string{}
	for _, feature := range features {
		if feature.VisitCount >= int(veryHighFreqThreshold) {
			veryHighFreqURLs = append(veryHighFreqURLs, feature.URL)
		}
	}
	log.Printf("极高频URL数量: %d", len(veryHighFreqURLs))

	if len(veryHighFreqURLs) >= minGroupSize {
		groups = append(groups, models.AIGroup{
			ID:          fmt.Sprintf("group_%d", groupID),
			Name:        "极高频访问",
			Description: "访问频率极高的网站",
			Color:       "#e74c3c",
			Icon:        "🚀",
			CreatedAt:   time.Now(),
			URLs:        veryHighFreqURLs,
			URLCount:    len(veryHighFreqURLs),
			Confidence:  0.95,
		})
		log.Printf("创建极高频分组: %d个URL", len(veryHighFreqURLs))
		groupID++
	}

	// 步骤5: 创建高频访问组
	log.Printf("步骤5: 创建高频访问组")
	highFreqURLs := []string{}
	for _, feature := range features {
		if feature.VisitCount >= int(highFreqThreshold) && feature.VisitCount < int(veryHighFreqThreshold) {
			highFreqURLs = append(highFreqURLs, feature.URL)
		}
	}
	log.Printf("高频URL数量: %d", len(highFreqURLs))

	if len(highFreqURLs) >= minGroupSize {
		groups = append(groups, models.AIGroup{
			ID:          fmt.Sprintf("group_%d", groupID),
			Name:        "高频访问",
			Description: "访问频率很高的网站",
			Color:       "#ff6b6b",
			Icon:        "🔥",
			CreatedAt:   time.Now(),
			URLs:        highFreqURLs,
			URLCount:    len(highFreqURLs),
			Confidence:  0.9,
		})
		log.Printf("创建高频分组: %d个URL", len(highFreqURLs))
		groupID++
	}

	// 步骤6: 创建中频访问组
	log.Printf("步骤6: 创建中频访问组")
	mediumFreqURLs := []string{}
	for _, feature := range features {
		if feature.VisitCount >= int(mediumFreqThreshold) && feature.VisitCount < int(highFreqThreshold) {
			mediumFreqURLs = append(mediumFreqURLs, feature.URL)
		}
	}
	log.Printf("中频URL数量: %d", len(mediumFreqURLs))

	if len(mediumFreqURLs) >= minGroupSize {
		groups = append(groups, models.AIGroup{
			ID:          fmt.Sprintf("group_%d", groupID),
			Name:        "中频访问",
			Description: "访问频率中等的网站",
			Color:       "#4ecdc4",
			Icon:        "⭐",
			CreatedAt:   time.Now(),
			URLs:        mediumFreqURLs,
			URLCount:    len(mediumFreqURLs),
			Confidence:  0.7,
		})
		log.Printf("创建中频分组: %d个URL", len(mediumFreqURLs))
		groupID++
	}

	// 步骤7: 创建低频访问组
	log.Printf("步骤7: 创建低频访问组")
	lowFreqURLs := []string{}
	for _, feature := range features {
		if feature.VisitCount >= int(veryLowFreqThreshold) && feature.VisitCount < int(mediumFreqThreshold) {
			lowFreqURLs = append(lowFreqURLs, feature.URL)
		}
	}
	log.Printf("低频URL数量: %d", len(lowFreqURLs))

	if len(lowFreqURLs) >= minGroupSize {
		groups = append(groups, models.AIGroup{
			ID:          fmt.Sprintf("group_%d", groupID),
			Name:        "低频访问",
			Description: "访问频率较低的网站",
			Color:       "#95a5a6",
			Icon:        "📌",
			CreatedAt:   time.Now(),
			URLs:        lowFreqURLs,
			URLCount:    len(lowFreqURLs),
			Confidence:  0.5,
		})
		log.Printf("创建低频分组: %d个URL", len(lowFreqURLs))
		groupID++
	}

	// 步骤8: 创建极低频访问组
	log.Printf("步骤8: 创建极低频访问组")
	veryLowFreqURLs := []string{}
	for _, feature := range features {
		if feature.VisitCount < int(veryLowFreqThreshold) {
			veryLowFreqURLs = append(veryLowFreqURLs, feature.URL)
		}
	}
	log.Printf("极低频URL数量: %d", len(veryLowFreqURLs))

	if len(veryLowFreqURLs) >= minGroupSize {
		groups = append(groups, models.AIGroup{
			ID:          fmt.Sprintf("group_%d", groupID),
			Name:        "极低频访问",
			Description: "访问频率极低的网站",
			Color:       "#7f8c8d",
			Icon:        "🔍",
			CreatedAt:   time.Now(),
			URLs:        veryLowFreqURLs,
			URLCount:    len(veryLowFreqURLs),
			Confidence:  0.3,
		})
		log.Printf("创建极低频分组: %d个URL", len(veryLowFreqURLs))
		groupID++
	}

	// 步骤9: 确保至少5个分组
	log.Printf("步骤9: 检查分组数量，确保至少5个分组")
	if len(groups) < 5 {
		log.Printf("当前分组数量: %d，少于5个，需要补充分组", len(groups))

		// 如果分组不足5个，按访问次数等分
		remainingURLs := []string{}
		for _, feature := range features {
			// 检查是否已经在任何分组中
			inGroup := false
			for _, group := range groups {
				for _, url := range group.URLs {
					if url == feature.URL {
						inGroup = true
						break
					}
				}
				if inGroup {
					break
				}
			}
			if !inGroup {
				remainingURLs = append(remainingURLs, feature.URL)
			}
		}

		log.Printf("剩余未分组URL数量: %d", len(remainingURLs))

		// 将剩余URL按访问次数等分成多个组
		groupsPerRemaining := (5 - len(groups)) + 1
		urlsPerGroup := len(remainingURLs) / groupsPerRemaining
		if urlsPerGroup < 1 {
			urlsPerGroup = 1
		}

		log.Printf("将剩余URL分成 %d 组，每组约 %d 个URL", groupsPerRemaining, urlsPerGroup)

		for i := 0; i < groupsPerRemaining && len(remainingURLs) > 0; i++ {
			start := i * urlsPerGroup
			end := start + urlsPerGroup
			if end > len(remainingURLs) {
				end = len(remainingURLs)
			}
			if start >= len(remainingURLs) {
				break
			}

			groupURLs := remainingURLs[start:end]
			groupName := fmt.Sprintf("补充分组%d", i+1)

			groups = append(groups, models.AIGroup{
				ID:          fmt.Sprintf("group_%d", groupID),
				Name:        groupName,
				Description: fmt.Sprintf("按访问频率补充的分组%d", i+1),
				Color:       fmt.Sprintf("#%02x%02x%02x", 100+i*30, 150+i*20, 200+i*10),
				Icon:        "📂",
				CreatedAt:   time.Now(),
				URLs:        groupURLs,
				URLCount:    len(groupURLs),
				Confidence:  0.4,
			})
			log.Printf("创建补充分组 %s: %d个URL", groupName, len(groupURLs))
			groupID++
		}
	}

	log.Printf("=== 频率分组算法完成 ===")
	log.Printf("最终分组数量: %d", len(groups))
	for i, group := range groups {
		log.Printf("分组 %d: %s (%d个URL)", i+1, group.Name, group.URLCount)
	}

	return groups, nil
}

// 时间模式分组算法实现
type TimePatternGroupingAlgorithm struct{}

func (t *TimePatternGroupingAlgorithm) GetName() string {
	return "time_pattern"
}

func (t *TimePatternGroupingAlgorithm) GetDescription() string {
	return "基于时间访问模式的分组算法"
}

func (t *TimePatternGroupingAlgorithm) GroupURLs(features []models.URLFeature, config models.AIGroupingConfig) ([]models.AIGroup, error) {
	log.Printf("=== 开始时间模式分组算法 ===")
	log.Printf("输入特征数量: %d", len(features))

	if len(features) == 0 {
		log.Printf("特征为空，返回空分组")
		return []models.AIGroup{}, nil
	}

	// 步骤1: 分析时间模式
	log.Printf("步骤1: 分析URL访问时间模式")
	workdayURLs := []string{}
	weekendURLs := []string{}
	morningURLs := []string{}
	afternoonURLs := []string{}
	eveningURLs := []string{}
	nightURLs := []string{}
	earlyMorningURLs := []string{}
	lateNightURLs := []string{}

	workdayCount := 0
	weekendCount := 0
	morningCount := 0
	afternoonCount := 0
	eveningCount := 0
	nightCount := 0
	earlyMorningCount := 0
	lateNightCount := 0

	for _, feature := range features {
		log.Printf("分析URL: %s", feature.URL)

		// 分析访问时间模式
		featureWorkdayCount := 0
		featureWeekendCount := 0
		featureMorningCount := 0
		featureAfternoonCount := 0
		featureEveningCount := 0
		featureNightCount := 0
		featureEarlyMorningCount := 0
		featureLateNightCount := 0

		for hour, visits := range feature.VisitPattern {
			if visits > 0 {
				log.Printf("  小时 %d: %d 次访问", hour, visits)

				// 工作日/周末模式（简化处理）
				if hour >= 9 && hour <= 17 {
					featureWorkdayCount += visits
					workdayCount += visits
				} else {
					featureWeekendCount += visits
					weekendCount += visits
				}

				// 更细粒度的时间段模式
				if hour >= 5 && hour < 8 {
					featureEarlyMorningCount += visits
					earlyMorningCount += visits
				} else if hour >= 8 && hour < 12 {
					featureMorningCount += visits
					morningCount += visits
				} else if hour >= 12 && hour < 18 {
					featureAfternoonCount += visits
					afternoonCount += visits
				} else if hour >= 18 && hour < 22 {
					featureEveningCount += visits
					eveningCount += visits
				} else if hour >= 22 && hour < 24 {
					featureLateNightCount += visits
					lateNightCount += visits
				} else {
					featureNightCount += visits
					nightCount += visits
				}
			}
		}

		// 根据主要访问时间分类
		totalVisits := featureWorkdayCount + featureWeekendCount
		if totalVisits > 0 {
			workdayRatio := float64(featureWorkdayCount) / float64(totalVisits)
			log.Printf("  工作日访问比例: %.2f", workdayRatio)

			if workdayRatio > 0.6 {
				workdayURLs = append(workdayURLs, feature.URL)
				log.Printf("  分类为: 工作日访问")
			} else if workdayRatio < 0.4 {
				weekendURLs = append(weekendURLs, feature.URL)
				log.Printf("  分类为: 周末访问")
			}
		}

		// 时间段分类
		totalTimeVisits := featureEarlyMorningCount + featureMorningCount + featureAfternoonCount + featureEveningCount + featureLateNightCount + featureNightCount
		if totalTimeVisits > 0 {
			earlyMorningRatio := float64(featureEarlyMorningCount) / float64(totalTimeVisits)
			morningRatio := float64(featureMorningCount) / float64(totalTimeVisits)
			afternoonRatio := float64(featureAfternoonCount) / float64(totalTimeVisits)
			eveningRatio := float64(featureEveningCount) / float64(totalTimeVisits)
			lateNightRatio := float64(featureLateNightCount) / float64(totalTimeVisits)
			nightRatio := float64(featureNightCount) / float64(totalTimeVisits)

			log.Printf("  时间段比例 - 清晨:%.2f 早晨:%.2f 下午:%.2f 晚上:%.2f 深夜:%.2f 夜间:%.2f",
				earlyMorningRatio, morningRatio, afternoonRatio, eveningRatio, lateNightRatio, nightRatio)

			maxRatio := math.Max(math.Max(math.Max(earlyMorningRatio, morningRatio), math.Max(afternoonRatio, eveningRatio)), math.Max(lateNightRatio, nightRatio))

			if maxRatio == earlyMorningRatio {
				earlyMorningURLs = append(earlyMorningURLs, feature.URL)
				log.Printf("  分类为: 清晨访问")
			} else if maxRatio == morningRatio {
				morningURLs = append(morningURLs, feature.URL)
				log.Printf("  分类为: 早晨访问")
			} else if maxRatio == afternoonRatio {
				afternoonURLs = append(afternoonURLs, feature.URL)
				log.Printf("  分类为: 下午访问")
			} else if maxRatio == eveningRatio {
				eveningURLs = append(eveningURLs, feature.URL)
				log.Printf("  分类为: 晚上访问")
			} else if maxRatio == lateNightRatio {
				lateNightURLs = append(lateNightURLs, feature.URL)
				log.Printf("  分类为: 深夜访问")
			} else {
				nightURLs = append(nightURLs, feature.URL)
				log.Printf("  分类为: 夜间访问")
			}
		}
	}

	// 步骤2: 统计各时间段URL数量
	log.Printf("步骤2: 统计各时间段URL数量")
	log.Printf("工作日URL数量: %d", len(workdayURLs))
	log.Printf("周末URL数量: %d", len(weekendURLs))
	log.Printf("清晨URL数量: %d", len(earlyMorningURLs))
	log.Printf("早晨URL数量: %d", len(morningURLs))
	log.Printf("下午URL数量: %d", len(afternoonURLs))
	log.Printf("晚上URL数量: %d", len(eveningURLs))
	log.Printf("深夜URL数量: %d", len(lateNightURLs))
	log.Printf("夜间URL数量: %d", len(nightURLs))

	var groups []models.AIGroup
	groupID := 1

	// 步骤3: 创建时间模式分组
	log.Printf("步骤3: 创建时间模式分组")
	timeGroups := []struct {
		name        string
		description string
		urls        []string
		color       string
		icon        string
		confidence  float64
	}{
		{"工作日访问", "主要在工作日访问的网站", workdayURLs, "#3498db", "💼", 0.8},
		{"周末访问", "主要在周末访问的网站", weekendURLs, "#e74c3c", "🎉", 0.8},
		{"清晨访问", "主要在清晨访问的网站", earlyMorningURLs, "#f39c12", "🌅", 0.7},
		{"早晨访问", "主要在早晨访问的网站", morningURLs, "#e67e22", "☀️", 0.7},
		{"下午访问", "主要在下午访问的网站", afternoonURLs, "#2ecc71", "🌞", 0.7},
		{"晚上访问", "主要在晚上访问的网站", eveningURLs, "#9b59b6", "🌙", 0.7},
		{"深夜访问", "主要在深夜访问的网站", lateNightURLs, "#34495e", "🌃", 0.6},
		{"夜间访问", "主要在夜间访问的网站", nightURLs, "#2c3e50", "🌌", 0.6},
	}

	for _, tg := range timeGroups {
		if len(tg.urls) >= config.MinGroupSize {
			groups = append(groups, models.AIGroup{
				ID:          fmt.Sprintf("group_%d", groupID),
				Name:        tg.name,
				Description: tg.description,
				Color:       tg.color,
				Icon:        tg.icon,
				CreatedAt:   time.Now(),
				URLs:        tg.urls,
				URLCount:    len(tg.urls),
				Confidence:  tg.confidence,
			})
			log.Printf("创建时间分组: %s (%d个URL)", tg.name, len(tg.urls))
			groupID++
		} else {
			log.Printf("跳过分组 %s: URL数量 %d 小于最小要求 %d", tg.name, len(tg.urls), config.MinGroupSize)
		}
	}

	// 步骤4: 确保至少5个分组
	log.Printf("步骤4: 检查分组数量，确保至少5个分组")
	if len(groups) < 5 {
		log.Printf("当前分组数量: %d，少于5个，需要补充分组", len(groups))

		// 如果分组不足5个，按访问时间等分
		remainingURLs := []string{}
		for _, feature := range features {
			// 检查是否已经在任何分组中
			inGroup := false
			for _, group := range groups {
				for _, url := range group.URLs {
					if url == feature.URL {
						inGroup = true
						break
					}
				}
				if inGroup {
					break
				}
			}
			if !inGroup {
				remainingURLs = append(remainingURLs, feature.URL)
			}
		}

		log.Printf("剩余未分组URL数量: %d", len(remainingURLs))

		// 将剩余URL按访问时间等分成多个组
		groupsPerRemaining := (5 - len(groups)) + 1
		urlsPerGroup := len(remainingURLs) / groupsPerRemaining
		if urlsPerGroup < 1 {
			urlsPerGroup = 1
		}

		log.Printf("将剩余URL分成 %d 组，每组约 %d 个URL", groupsPerRemaining, urlsPerGroup)

		for i := 0; i < groupsPerRemaining && len(remainingURLs) > 0; i++ {
			start := i * urlsPerGroup
			end := start + urlsPerGroup
			if end > len(remainingURLs) {
				end = len(remainingURLs)
			}
			if start >= len(remainingURLs) {
				break
			}

			groupURLs := remainingURLs[start:end]
			groupName := fmt.Sprintf("时间补充分组%d", i+1)

			groups = append(groups, models.AIGroup{
				ID:          fmt.Sprintf("group_%d", groupID),
				Name:        groupName,
				Description: fmt.Sprintf("按时间模式补充的分组%d", i+1),
				Color:       fmt.Sprintf("#%02x%02x%02x", 120+i*25, 160+i*15, 180+i*20),
				Icon:        "⏰",
				CreatedAt:   time.Now(),
				URLs:        groupURLs,
				URLCount:    len(groupURLs),
				Confidence:  0.4,
			})
			log.Printf("创建时间补充分组 %s: %d个URL", groupName, len(groupURLs))
			groupID++
		}
	}

	log.Printf("=== 时间模式分组算法完成 ===")
	log.Printf("最终分组数量: %d", len(groups))
	for i, group := range groups {
		log.Printf("分组 %d: %s (%d个URL)", i+1, group.Name, group.URLCount)
	}

	return groups, nil
}

// 内容相似性分组算法实现
type ContentSimilarityGroupingAlgorithm struct{}

func (c *ContentSimilarityGroupingAlgorithm) GetName() string {
	return "content_similarity"
}

func (c *ContentSimilarityGroupingAlgorithm) GetDescription() string {
	return "基于内容相似性的分组算法"
}

func (c *ContentSimilarityGroupingAlgorithm) GroupURLs(features []models.URLFeature, config models.AIGroupingConfig) ([]models.AIGroup, error) {
	log.Printf("=== 开始内容相似性分组算法 ===")
	log.Printf("输入特征数量: %d", len(features))

	if len(features) == 0 {
		log.Printf("特征为空，返回空分组")
		return []models.AIGroup{}, nil
	}

	// 步骤1: 计算URL相似度矩阵
	log.Printf("步骤1: 计算URL相似度矩阵")
	similarityMatrix := make([][]float64, len(features))
	for i := range similarityMatrix {
		similarityMatrix[i] = make([]float64, len(features))
	}

	similarityCount := 0
	for i := 0; i < len(features); i++ {
		for j := i + 1; j < len(features); j++ {
			similarity := c.calculateSimilarity(features[i], features[j])
			similarityMatrix[i][j] = similarity
			similarityMatrix[j][i] = similarity
			similarityCount++

			if similarityCount%10 == 0 {
				log.Printf("  已计算 %d 个相似度对", similarityCount)
			}
		}
		similarityMatrix[i][i] = 1.0
	}

	log.Printf("相似度矩阵计算完成，共计算 %d 个相似度对", similarityCount)

	// 步骤2: 设置聚类阈值
	log.Printf("步骤2: 设置聚类阈值")
	threshold := config.SimilarityThreshold
	if threshold <= 0 {
		threshold = 0.3
	}
	log.Printf("相似度阈值: %.2f", threshold)

	// 步骤3: 执行聚类分组
	log.Printf("步骤3: 执行聚类分组")
	groups := c.performClustering(features, similarityMatrix, threshold, config)
	log.Printf("聚类完成，生成 %d 个分组", len(groups))

	// 步骤4: 确保至少5个分组
	log.Printf("步骤4: 检查分组数量，确保至少5个分组")
	if len(groups) < 5 {
		log.Printf("当前分组数量: %d，少于5个，需要补充分组", len(groups))

		// 如果分组不足5个，降低阈值重新聚类
		log.Printf("降低相似度阈值重新聚类")
		lowerThresholds := []float64{0.2, 0.1, 0.05, 0.01}

		for _, newThreshold := range lowerThresholds {
			if len(groups) >= 5 {
				break
			}

			log.Printf("尝试阈值 %.2f", newThreshold)
			groups = c.performClustering(features, similarityMatrix, newThreshold, config)
			log.Printf("新阈值 %.2f 生成 %d 个分组", newThreshold, len(groups))
		}

		// 如果仍然不足5个分组，强制分割
		if len(groups) < 5 {
			log.Printf("强制分割剩余URL以确保至少5个分组")
			groups = c.forceSplitIntoGroups(features, groups, config)
		}
	}

	log.Printf("=== 内容相似性分组算法完成 ===")
	log.Printf("最终分组数量: %d", len(groups))
	for i, group := range groups {
		log.Printf("分组 %d: %s (%d个URL)", i+1, group.Name, group.URLCount)
	}

	return groups, nil
}

// calculateSimilarity 计算两个URL特征的相似度
func (c *ContentSimilarityGroupingAlgorithm) calculateSimilarity(f1, f2 models.URLFeature) float64 {
	// 域名相似度
	domainSim := c.domainSimilarity(f1.Domain, f2.Domain)

	// 路径相似度
	pathSim := c.pathSimilarity(f1.Path, f2.Path)

	// 标题相似度
	titleSim := c.titleSimilarity(f1.Title, f2.Title)

	// 关键词相似度
	keywordSim := c.keywordSimilarity(f1.Keywords, f2.Keywords)

	// 加权平均
	return domainSim*0.4 + pathSim*0.3 + titleSim*0.2 + keywordSim*0.1
}

// domainSimilarity 域名相似度
func (c *ContentSimilarityGroupingAlgorithm) domainSimilarity(domain1, domain2 string) float64 {
	if domain1 == domain2 {
		return 1.0
	}

	// 提取主域名
	main1 := c.extractMainDomain(domain1)
	main2 := c.extractMainDomain(domain2)

	if main1 == main2 {
		return 0.8
	}

	// 计算编辑距离相似度
	return c.editDistanceSimilarity(main1, main2)
}

// extractMainDomain 提取主域名
func (c *ContentSimilarityGroupingAlgorithm) extractMainDomain(domain string) string {
	parts := strings.Split(domain, ".")
	if len(parts) >= 2 {
		return strings.Join(parts[len(parts)-2:], ".")
	}
	return domain
}

// pathSimilarity 路径相似度
func (c *ContentSimilarityGroupingAlgorithm) pathSimilarity(path1, path2 string) float64 {
	if path1 == path2 {
		return 1.0
	}

	// 路径层级相似度
	parts1 := strings.Split(strings.Trim(path1, "/"), "/")
	parts2 := strings.Split(strings.Trim(path2, "/"), "/")

	if len(parts1) == 0 && len(parts2) == 0 {
		return 1.0
	}

	// 计算最长公共子序列
	lcs := c.longestCommonSubsequence(parts1, parts2)
	maxLen := math.Max(float64(len(parts1)), float64(len(parts2)))

	return float64(lcs) / maxLen
}

// titleSimilarity 标题相似度
func (c *ContentSimilarityGroupingAlgorithm) titleSimilarity(title1, title2 string) float64 {
	if title1 == title2 {
		return 1.0
	}

	// 转换为小写并分词
	words1 := strings.Fields(strings.ToLower(title1))
	words2 := strings.Fields(strings.ToLower(title2))

	if len(words1) == 0 && len(words2) == 0 {
		return 1.0
	}

	// 计算Jaccard相似度
	return c.jaccardSimilarity(words1, words2)
}

// keywordSimilarity 关键词相似度
func (c *ContentSimilarityGroupingAlgorithm) keywordSimilarity(keywords1, keywords2 []string) float64 {
	if len(keywords1) == 0 && len(keywords2) == 0 {
		return 1.0
	}

	return c.jaccardSimilarity(keywords1, keywords2)
}

// jaccardSimilarity 计算Jaccard相似度
func (c *ContentSimilarityGroupingAlgorithm) jaccardSimilarity(set1, set2 []string) float64 {
	if len(set1) == 0 && len(set2) == 0 {
		return 1.0
	}

	set1Map := make(map[string]bool)
	for _, item := range set1 {
		set1Map[item] = true
	}

	set2Map := make(map[string]bool)
	for _, item := range set2 {
		set2Map[item] = true
	}

	intersection := 0
	for item := range set1Map {
		if set2Map[item] {
			intersection++
		}
	}

	union := len(set1Map) + len(set2Map) - intersection

	if union == 0 {
		return 0.0
	}

	return float64(intersection) / float64(union)
}

// editDistanceSimilarity 编辑距离相似度
func (c *ContentSimilarityGroupingAlgorithm) editDistanceSimilarity(s1, s2 string) float64 {
	if s1 == s2 {
		return 1.0
	}

	dist := c.editDistance(s1, s2)
	maxLen := math.Max(float64(len(s1)), float64(len(s2)))

	if maxLen == 0 {
		return 1.0
	}

	return 1.0 - float64(dist)/maxLen
}

// editDistance 计算编辑距离
func (c *ContentSimilarityGroupingAlgorithm) editDistance(s1, s2 string) int {
	m, n := len(s1), len(s2)
	dp := make([][]int, m+1)
	for i := range dp {
		dp[i] = make([]int, n+1)
	}

	for i := 0; i <= m; i++ {
		dp[i][0] = i
	}
	for j := 0; j <= n; j++ {
		dp[0][j] = j
	}

	for i := 1; i <= m; i++ {
		for j := 1; j <= n; j++ {
			if s1[i-1] == s2[j-1] {
				dp[i][j] = dp[i-1][j-1]
			} else {
				dp[i][j] = 1 + int(math.Min(float64(dp[i-1][j]), math.Min(float64(dp[i][j-1]), float64(dp[i-1][j-1]))))
			}
		}
	}

	return dp[m][n]
}

// longestCommonSubsequence 最长公共子序列
func (c *ContentSimilarityGroupingAlgorithm) longestCommonSubsequence(seq1, seq2 []string) int {
	m, n := len(seq1), len(seq2)
	dp := make([][]int, m+1)
	for i := range dp {
		dp[i] = make([]int, n+1)
	}

	for i := 1; i <= m; i++ {
		for j := 1; j <= n; j++ {
			if seq1[i-1] == seq2[j-1] {
				dp[i][j] = dp[i-1][j-1] + 1
			} else {
				dp[i][j] = int(math.Max(float64(dp[i-1][j]), float64(dp[i][j-1])))
			}
		}
	}

	return dp[m][n]
}

// performClustering 执行聚类
func (c *ContentSimilarityGroupingAlgorithm) performClustering(features []models.URLFeature, similarityMatrix [][]float64, threshold float64, config models.AIGroupingConfig) []models.AIGroup {
	log.Printf("开始执行聚类，阈值: %.2f", threshold)

	visited := make([]bool, len(features))
	var groups []models.AIGroup
	groupID := 1
	processedCount := 0

	for i := 0; i < len(features); i++ {
		if visited[i] {
			continue
		}

		log.Printf("处理特征 %d: %s", i+1, features[i].URL)

		// 找到与当前URL相似的所有URL
		var groupURLs []string
		var groupFeatures []models.URLFeature

		for j := i; j < len(features); j++ {
			if !visited[j] && similarityMatrix[i][j] >= threshold {
				groupURLs = append(groupURLs, features[j].URL)
				groupFeatures = append(groupFeatures, features[j])
				visited[j] = true
				log.Printf("  添加相似URL: %s (相似度: %.2f)", features[j].URL, similarityMatrix[i][j])
			}
		}

		// 如果组大小符合要求，创建分组
		if len(groupURLs) >= config.MinGroupSize {
			groupName := c.generateGroupName(groupFeatures)
			groupDescription := c.generateGroupDescription(groupFeatures)

			groups = append(groups, models.AIGroup{
				ID:          fmt.Sprintf("group_%d", groupID),
				Name:        groupName,
				Description: groupDescription,
				Color:       c.generateGroupColor(groupID),
				Icon:        c.generateGroupIcon(groupFeatures),
				CreatedAt:   time.Now(),
				URLs:        groupURLs,
				URLCount:    len(groupURLs),
				Confidence:  c.calculateGroupConfidence(groupFeatures, similarityMatrix),
			})
			log.Printf("创建聚类分组 %d: %s (%d个URL)", groupID, groupName, len(groupURLs))
			groupID++
		} else {
			log.Printf("跳过分组: URL数量 %d 小于最小要求 %d", len(groupURLs), config.MinGroupSize)
		}

		processedCount++
		if processedCount%10 == 0 {
			log.Printf("已处理 %d 个特征", processedCount)
		}
	}

	log.Printf("聚类完成，生成 %d 个分组", len(groups))
	return groups
}

// forceSplitIntoGroups 强制分割成至少5个分组
func (c *ContentSimilarityGroupingAlgorithm) forceSplitIntoGroups(features []models.URLFeature, existingGroups []models.AIGroup, config models.AIGroupingConfig) []models.AIGroup {
	log.Printf("强制分割URL以确保至少5个分组")

	// 收集所有已分组的URL
	groupedURLs := make(map[string]bool)
	for _, group := range existingGroups {
		for _, url := range group.URLs {
			groupedURLs[url] = true
		}
	}

	// 找到未分组的URL
	var ungroupedFeatures []models.URLFeature
	for _, feature := range features {
		if !groupedURLs[feature.URL] {
			ungroupedFeatures = append(ungroupedFeatures, feature)
		}
	}

	log.Printf("未分组URL数量: %d", len(ungroupedFeatures))

	// 将未分组的URL按访问次数排序
	sort.Slice(ungroupedFeatures, func(i, j int) bool {
		return ungroupedFeatures[i].VisitCount > ungroupedFeatures[j].VisitCount
	})

	// 计算需要创建的分组数量
	targetGroupCount := 5 - len(existingGroups)
	if targetGroupCount <= 0 {
		return existingGroups
	}

	// 将未分组URL等分成多个组
	urlsPerGroup := len(ungroupedFeatures) / targetGroupCount
	if urlsPerGroup < 1 {
		urlsPerGroup = 1
	}

	log.Printf("将 %d 个未分组URL分成 %d 组，每组约 %d 个URL", len(ungroupedFeatures), targetGroupCount, urlsPerGroup)

	groups := make([]models.AIGroup, len(existingGroups))
	copy(groups, existingGroups)
	groupID := len(existingGroups) + 1

	for i := 0; i < targetGroupCount && len(ungroupedFeatures) > 0; i++ {
		start := i * urlsPerGroup
		end := start + urlsPerGroup
		if end > len(ungroupedFeatures) {
			end = len(ungroupedFeatures)
		}
		if start >= len(ungroupedFeatures) {
			break
		}

		groupFeatures := ungroupedFeatures[start:end]
		var groupURLs []string
		for _, feature := range groupFeatures {
			groupURLs = append(groupURLs, feature.URL)
		}

		groupName := fmt.Sprintf("强制分组%d", i+1)
		groupDescription := fmt.Sprintf("按访问频率强制分割的分组%d", i+1)

		groups = append(groups, models.AIGroup{
			ID:          fmt.Sprintf("group_%d", groupID),
			Name:        groupName,
			Description: groupDescription,
			Color:       fmt.Sprintf("#%02x%02x%02x", 80+i*40, 120+i*30, 160+i*20),
			Icon:        "🔧",
			CreatedAt:   time.Now(),
			URLs:        groupURLs,
			URLCount:    len(groupURLs),
			Confidence:  0.3,
		})

		log.Printf("创建强制分组 %s: %d个URL", groupName, len(groupURLs))
		groupID++
	}

	log.Printf("强制分割完成，最终分组数量: %d", len(groups))
	return groups
}

// generateGroupName 生成分组名称
func (c *ContentSimilarityGroupingAlgorithm) generateGroupName(features []models.URLFeature) string {
	if len(features) == 0 {
		return "未命名分组"
	}

	// 基于域名生成名称
	domainCount := make(map[string]int)
	for _, feature := range features {
		mainDomain := c.extractMainDomain(feature.Domain)
		domainCount[mainDomain]++
	}

	// 找到最常见的域名
	maxCount := 0
	commonDomain := ""
	for domain, count := range domainCount {
		if count > maxCount {
			maxCount = count
			commonDomain = domain
		}
	}

	if commonDomain != "" {
		return commonDomain + " 相关"
	}

	// 基于关键词生成名称
	keywordCount := make(map[string]int)
	for _, feature := range features {
		for _, keyword := range feature.Keywords {
			keywordCount[keyword]++
		}
	}

	// 找到最常见的关键词
	maxKeywordCount := 0
	commonKeyword := ""
	for keyword, count := range keywordCount {
		if count > maxKeywordCount {
			maxKeywordCount = count
			commonKeyword = keyword
		}
	}

	if commonKeyword != "" {
		return commonKeyword + " 相关"
	}

	return "相似内容分组"
}

// generateGroupDescription 生成分组描述
func (c *ContentSimilarityGroupingAlgorithm) generateGroupDescription(features []models.URLFeature) string {
	if len(features) == 0 {
		return "基于内容相似性自动分组"
	}

	// 统计域名分布
	domainCount := make(map[string]int)
	for _, feature := range features {
		mainDomain := c.extractMainDomain(feature.Domain)
		domainCount[mainDomain]++
	}

	if len(domainCount) == 1 {
		for domain := range domainCount {
			return fmt.Sprintf("主要来自 %s 的网站", domain)
		}
	}

	return fmt.Sprintf("包含 %d 个相似网站的分组", len(features))
}

// generateGroupColor 生成分组颜色
func (c *ContentSimilarityGroupingAlgorithm) generateGroupColor(groupID int) string {
	colors := []string{
		"#e74c3c", "#3498db", "#2ecc71", "#f39c12", "#9b59b6",
		"#1abc9c", "#34495e", "#e67e22", "#95a5a6", "#f1c40f",
	}
	return colors[groupID%len(colors)]
}

// generateGroupIcon 生成分组图标
func (c *ContentSimilarityGroupingAlgorithm) generateGroupIcon(features []models.URLFeature) string {
	icons := []string{"🔗", "📁", "🌐", "📊", "💼", "🎯", "⭐", "📝"}
	return icons[len(features)%len(icons)]
}

// calculateGroupConfidence 计算分组置信度
func (c *ContentSimilarityGroupingAlgorithm) calculateGroupConfidence(features []models.URLFeature, similarityMatrix [][]float64) float64 {
	if len(features) <= 1 {
		return 1.0
	}

	totalSimilarity := 0.0
	pairCount := 0

	for i := 0; i < len(features); i++ {
		for j := i + 1; j < len(features); j++ {
			// 找到在原始features数组中的索引
			idx1, idx2 := -1, -1
			for k, f := range features {
				if f.URL == features[i].URL {
					idx1 = k
				}
				if f.URL == features[j].URL {
					idx2 = k
				}
			}

			if idx1 >= 0 && idx2 >= 0 && idx1 < len(similarityMatrix) && idx2 < len(similarityMatrix[idx1]) {
				totalSimilarity += similarityMatrix[idx1][idx2]
				pairCount++
			}
		}
	}

	if pairCount == 0 {
		return 0.5
	}

	return totalSimilarity / float64(pairCount)
}

// AI增强分组算法实现
type AIEnhancedGroupingAlgorithm struct{}

func (a *AIEnhancedGroupingAlgorithm) GetName() string {
	return "ai_enhanced"
}

func (a *AIEnhancedGroupingAlgorithm) GetDescription() string {
	return "AI增强的分组算法，结合多种策略"
}

func (a *AIEnhancedGroupingAlgorithm) GroupURLs(features []models.URLFeature, config models.AIGroupingConfig) ([]models.AIGroup, error) {
	log.Printf("=== 开始AI增强分组算法 ===")
	log.Printf("输入特征数量: %d", len(features))

	if len(features) == 0 {
		log.Printf("特征为空，返回空分组")
		return []models.AIGroup{}, nil
	}

	// 步骤1: 使用多种算法进行分组
	log.Printf("步骤1: 使用多种算法进行分组")

	// 1.1 频率分组
	log.Printf("1.1 执行频率分组")
	freqAlgo := &FrequencyGroupingAlgorithm{}
	freqGroups, err := freqAlgo.GroupURLs(features, config)
	if err != nil {
		log.Printf("频率分组失败: %v", err)
		freqGroups = []models.AIGroup{}
	} else {
		log.Printf("频率分组完成，生成 %d 个分组", len(freqGroups))
	}

	// 1.2 时间模式分组
	log.Printf("1.2 执行时间模式分组")
	timeAlgo := &TimePatternGroupingAlgorithm{}
	timeGroups, err := timeAlgo.GroupURLs(features, config)
	if err != nil {
		log.Printf("时间模式分组失败: %v", err)
		timeGroups = []models.AIGroup{}
	} else {
		log.Printf("时间模式分组完成，生成 %d 个分组", len(timeGroups))
	}

	// 1.3 内容相似性分组
	log.Printf("1.3 执行内容相似性分组")
	contentAlgo := &ContentSimilarityGroupingAlgorithm{}
	contentGroups, err := contentAlgo.GroupURLs(features, config)
	if err != nil {
		log.Printf("内容相似性分组失败: %v", err)
		contentGroups = []models.AIGroup{}
	} else {
		log.Printf("内容相似性分组完成，生成 %d 个分组", len(contentGroups))
	}

	// 步骤2: 合并和优化分组结果
	log.Printf("步骤2: 合并和优化分组结果")
	allGroups := []models.AIGroup{}
	allGroups = append(allGroups, freqGroups...)
	allGroups = append(allGroups, timeGroups...)
	allGroups = append(allGroups, contentGroups...)

	log.Printf("所有算法共生成 %d 个分组", len(allGroups))

	// 步骤3: 去重和合并相似分组
	log.Printf("步骤3: 去重和合并相似分组")
	mergedGroups := a.mergeSimilarGroups(allGroups, config)
	log.Printf("合并后分组数量: %d", len(mergedGroups))

	// 步骤4: 确保至少5个分组
	log.Printf("步骤4: 确保至少5个分组")
	if len(mergedGroups) < 5 {
		log.Printf("当前分组数量: %d，少于5个，需要补充分组", len(mergedGroups))

		// 使用混合策略补充分组
		remainingURLs := a.findUngroupedURLs(features, mergedGroups)
		log.Printf("剩余未分组URL数量: %d", len(remainingURLs))

		if len(remainingURLs) > 0 {
			// 按类别补充分组
			categoryGroups := a.createCategoryGroups(remainingURLs, features, config)
			mergedGroups = append(mergedGroups, categoryGroups...)
			log.Printf("添加类别分组后，总分组数量: %d", len(mergedGroups))
		}

		// 如果仍然不足5个分组，强制分割
		if len(mergedGroups) < 5 {
			log.Printf("强制分割以确保至少5个分组")
			mergedGroups = a.forceCreateGroups(features, mergedGroups, config)
		}
	}

	// 步骤5: 优化分组名称和描述
	log.Printf("步骤5: 优化分组名称和描述")
	optimizedGroups := a.optimizeGroupNames(mergedGroups, features)

	log.Printf("=== AI增强分组算法完成 ===")
	log.Printf("最终分组数量: %d", len(optimizedGroups))
	for i, group := range optimizedGroups {
		log.Printf("分组 %d: %s (%d个URL)", i+1, group.Name, group.URLCount)
	}

	return optimizedGroups, nil
}

// mergeSimilarGroups 合并相似的分组
func (a *AIEnhancedGroupingAlgorithm) mergeSimilarGroups(groups []models.AIGroup, config models.AIGroupingConfig) []models.AIGroup {
	log.Printf("开始合并相似分组")

	if len(groups) == 0 {
		return groups
	}

	merged := []models.AIGroup{}
	used := make([]bool, len(groups))

	for i, group1 := range groups {
		if used[i] {
			continue
		}

		log.Printf("检查分组: %s", group1.Name)
		currentGroup := group1
		used[i] = true

		// 查找相似的分组进行合并
		for j := i + 1; j < len(groups); j++ {
			if used[j] {
				continue
			}

			group2 := groups[j]
			similarity := a.calculateGroupSimilarity(currentGroup, group2)

			if similarity > 0.7 { // 相似度阈值
				log.Printf("  合并相似分组: %s (相似度: %.2f)", group2.Name, similarity)

				// 合并URL
				urlSet := make(map[string]bool)
				for _, url := range currentGroup.URLs {
					urlSet[url] = true
				}
				for _, url := range group2.URLs {
					urlSet[url] = true
				}

				var mergedURLs []string
				for url := range urlSet {
					mergedURLs = append(mergedURLs, url)
				}

				currentGroup.URLs = mergedURLs
				currentGroup.URLCount = len(mergedURLs)
				currentGroup.Name = fmt.Sprintf("%s+%s", currentGroup.Name, group2.Name)
				currentGroup.Confidence = (currentGroup.Confidence + group2.Confidence) / 2

				used[j] = true
			}
		}

		merged = append(merged, currentGroup)
		log.Printf("保留分组: %s (%d个URL)", currentGroup.Name, currentGroup.URLCount)
	}

	log.Printf("合并完成，从 %d 个分组合并为 %d 个分组", len(groups), len(merged))
	return merged
}

// calculateGroupSimilarity 计算两个分组的相似度
func (a *AIEnhancedGroupingAlgorithm) calculateGroupSimilarity(group1, group2 models.AIGroup) float64 {
	// 基于URL重叠度计算相似度
	urlSet1 := make(map[string]bool)
	for _, url := range group1.URLs {
		urlSet1[url] = true
	}

	urlSet2 := make(map[string]bool)
	for _, url := range group2.URLs {
		urlSet2[url] = true
	}

	intersection := 0
	for url := range urlSet1 {
		if urlSet2[url] {
			intersection++
		}
	}

	union := len(urlSet1) + len(urlSet2) - intersection
	if union == 0 {
		return 0.0
	}

	return float64(intersection) / float64(union)
}

// findUngroupedURLs 找到未分组的URL
func (a *AIEnhancedGroupingAlgorithm) findUngroupedURLs(features []models.URLFeature, groups []models.AIGroup) []string {
	groupedURLs := make(map[string]bool)
	for _, group := range groups {
		for _, url := range group.URLs {
			groupedURLs[url] = true
		}
	}

	var ungrouped []string
	for _, feature := range features {
		if !groupedURLs[feature.URL] {
			ungrouped = append(ungrouped, feature.URL)
		}
	}

	return ungrouped
}

// createCategoryGroups 按类别创建分组
func (a *AIEnhancedGroupingAlgorithm) createCategoryGroups(remainingURLs []string, features []models.URLFeature, config models.AIGroupingConfig) []models.AIGroup {
	log.Printf("按类别创建补充分组")

	// 按类别分组
	categoryMap := make(map[string][]string)
	for _, url := range remainingURLs {
		// 找到对应的特征
		var feature *models.URLFeature
		for _, f := range features {
			if f.URL == url {
				feature = &f
				break
			}
		}

		if feature != nil {
			category := feature.Category
			if category == "" {
				category = "其他"
			}
			categoryMap[category] = append(categoryMap[category], url)
		}
	}

	var groups []models.AIGroup
	groupID := 1

	for category, urls := range categoryMap {
		if len(urls) >= config.MinGroupSize {
			group := models.AIGroup{
				ID:          fmt.Sprintf("category_group_%d", groupID),
				Name:        category + "相关",
				Description: fmt.Sprintf("按类别 %s 自动分组", category),
				Color:       fmt.Sprintf("#%02x%02x%02x", 100+groupID*30, 150+groupID*20, 200+groupID*10),
				Icon:        "📁",
				CreatedAt:   time.Now(),
				URLs:        urls,
				URLCount:    len(urls),
				Confidence:  0.6,
			}
			groups = append(groups, group)
			log.Printf("创建类别分组: %s (%d个URL)", category, len(urls))
			groupID++
		}
	}

	return groups
}

// forceCreateGroups 强制创建分组以确保至少5个
func (a *AIEnhancedGroupingAlgorithm) forceCreateGroups(features []models.URLFeature, existingGroups []models.AIGroup, config models.AIGroupingConfig) []models.AIGroup {
	log.Printf("强制创建分组以确保至少5个分组")

	remainingURLs := a.findUngroupedURLs(features, existingGroups)
	if len(remainingURLs) == 0 {
		return existingGroups
	}

	// 按访问次数排序
	sort.Slice(remainingURLs, func(i, j int) bool {
		var countI, countJ int
		for _, f := range features {
			if f.URL == remainingURLs[i] {
				countI = f.VisitCount
			}
			if f.URL == remainingURLs[j] {
				countJ = f.VisitCount
			}
		}
		return countI > countJ
	})

	// 计算需要创建的分组数量
	targetCount := 5 - len(existingGroups)
	urlsPerGroup := len(remainingURLs) / targetCount
	if urlsPerGroup < 1 {
		urlsPerGroup = 1
	}

	groups := make([]models.AIGroup, len(existingGroups))
	copy(groups, existingGroups)
	groupID := len(existingGroups) + 1

	for i := 0; i < targetCount && len(remainingURLs) > 0; i++ {
		start := i * urlsPerGroup
		end := start + urlsPerGroup
		if end > len(remainingURLs) {
			end = len(remainingURLs)
		}
		if start >= len(remainingURLs) {
			break
		}

		groupURLs := remainingURLs[start:end]
		groupName := fmt.Sprintf("AI补充分组%d", i+1)

		group := models.AIGroup{
			ID:          fmt.Sprintf("ai_force_group_%d", groupID),
			Name:        groupName,
			Description: fmt.Sprintf("AI增强算法强制创建的分组%d", i+1),
			Color:       fmt.Sprintf("#%02x%02x%02x", 60+i*50, 100+i*40, 140+i*30),
			Icon:        "🤖",
			CreatedAt:   time.Now(),
			URLs:        groupURLs,
			URLCount:    len(groupURLs),
			Confidence:  0.4,
		}

		groups = append(groups, group)
		log.Printf("创建AI强制分组: %s (%d个URL)", groupName, len(groupURLs))
		groupID++
	}

	return groups
}

// optimizeGroupNames 优化分组名称和描述
func (a *AIEnhancedGroupingAlgorithm) optimizeGroupNames(groups []models.AIGroup, features []models.URLFeature) []models.AIGroup {
	log.Printf("优化分组名称和描述")

	optimized := make([]models.AIGroup, len(groups))
	copy(optimized, groups)

	for i, group := range optimized {
		// 基于URL特征优化名称
		if len(group.URLs) > 0 {
			// 找到第一个URL的特征
			var firstFeature *models.URLFeature
			for _, f := range features {
				if f.URL == group.URLs[0] {
					firstFeature = &f
					break
				}
			}

			if firstFeature != nil {
				// 基于域名优化名称
				domain := firstFeature.Domain
				if domain != "" {
					// 提取主域名
					parts := strings.Split(domain, ".")
					if len(parts) >= 2 {
						mainDomain := parts[len(parts)-2]
						if !strings.Contains(group.Name, mainDomain) {
							group.Name = fmt.Sprintf("%s (%s)", group.Name, mainDomain)
						}
					}
				}

				// 基于类别优化描述
				if firstFeature.Category != "" && firstFeature.Category != "其他" {
					group.Description = fmt.Sprintf("主要包含 %s 类别的网站", firstFeature.Category)
				}
			}
		}

		optimized[i] = group
	}

	return optimized
}
